import 'package:family_expense/features/journey/models/journey.dart';
import 'package:family_expense/features/journey/models/region.dart';
import 'package:family_expense/features/journey/services/journey_service.dart';
import 'package:family_expense/features/journey/services/region_service.dart';
import 'package:family_expense/features/journey/widgets/region_shared.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';

class EditJourneyResult {
  EditJourneyResult(this.dataUpdated, {this.journey});

  final bool dataUpdated;
  final Journey? journey;
}

class EditJourney extends StatefulWidget {
  const EditJourney({super.key, this.journey});

  final Journey? journey;

  @override
  State<EditJourney> createState() => _EditJourneyState();
}

class _EditJourneyState extends State<EditJourney> {
  final JourneyService _journeyService = JourneyService();
  final RegionService _regionService = RegionService();

  // Indicates current action is adding new data or updating data.
  // If [id] does not exist that means is adding new data.
  late final bool _addNew = widget.journey?.id == null;

  // Current journey data.
  Journey? _journey;

  List<Region>? _countries;

  @override
  void initState() {
    super.initState();

    _createJourney();
    _queryCountries();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvokedWithResult: _onPopInvokedWithResult,
      child: Scaffold(
        appBar: AppBar(title: Text(_addNew ? '添加' : '修改')),
        body: _buildForm(),
      ),
    );
  }

  /// Builds the input form.
  Widget _buildForm() {
    if (_journey == null) {
      return const MyPageTopCenterLoadingIndicator();
    }

    return ListView(
      padding: const EdgeInsets.all(10.0),
      children: [
        SimpleDetailListTile(
          title: const Text('国家/地区'),
          value: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              if (_journey!.region != null) RegionFlag(_journey!.region!),
              const SizedBox(width: 10.0),
              Text(_journey!.region?.title ?? ''),
            ],
          ),
          onTap: () {
            RegionShared.showRegionModalBottomSheet(context, _countries!, (
              region,
            ) {
              if (mounted) {
                // Triggers build.
                setState(() => _journey!.region = region);
              }

              // Closes modal.
              NavigatorHelper.pop(context);
            }, region: _journey!.region);
          },
        ),
        SimpleDetailListTile(
          title: const Text('开始日期'),
          value: Text(_journey!.startDate.formatDate(DatePatterns.longDate)),
          onTap: () async {
            final selectedDate = await showMyDatePicker(
              context,
              initialDate: _journey!.startDate,
              lastDate: _journey!.endDate,
            );

            if (selectedDate != null && mounted) {
              setState(() => _journey!.startDate = selectedDate);
            }
          },
        ),
        SimpleDetailListTile(
          title: const Text('结束日期'),
          value: Text(_journey!.endDate.formatDate(DatePatterns.longDate)),
          onTap: () async {
            final selectedDate = await showMyDatePicker(
              context,
              initialDate: _journey!.endDate,
              firstDate: _journey!.startDate,
            );

            if (selectedDate != null && mounted) {
              setState(() => _journey!.endDate = selectedDate);
            }
          },
        ),
        const SizedBox(height: 20.0),
        Container(
          margin: const EdgeInsets.only(top: 40.0),
          height: 44.0,
          child: PressStatusButton(
            onPressed: _save,
            disabledChild: const Text('正在保存', style: TextStyle(fontSize: 20.0)),
            child: _addNew
                ? _buildIconText(MdiIcons.plus, '添 加')
                : _buildIconText(MdiIcons.pencil, '修 改'),
          ),
        ),
      ],
    );
  }

  /// Builds a Text with an Icon on its left.
  Widget _buildIconText(IconData icon, String titile) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(
          icon,
          color: calculateContrastingColor(
            Theme.of(context).appBarTheme.backgroundColor!,
          ),
        ),
        const SizedBox(width: 20.0),
        Text(titile, style: const TextStyle(fontSize: 20.0)),
      ],
    );
  }

  /// Creates new instance of [IncomeExpenseDetail] based on current widget argument.
  void _createJourney() {
    _journey = widget.journey?.clone() ?? Journey();
  }

  Future<void> _queryCountries() async {
    final res = await _regionService.queryAll();

    if (mounted) {
      setState(() {
        _countries = res;
      });
    }
  }

  /// The [Form] only checks on input type fields.
  /// We have to validate the form selection manually.
  bool _validateForm() {
    if (_journey!.region == null) {
      showToast('请选择国家/地区');
      return false;
    }

    if (_journey!.startDate == null) {
      showToast('请选择开始日期');
      return false;
    }

    if (_journey!.endDate == null) {
      showToast('请选择结束日期');
      return false;
    }

    return true;
  }

  /// Saves the new [IncomeExpenseDetail] to server and pops.
  Future<void> _save() async {
    if (!_validateForm()) {
      return;
    }

    if (_addNew) {
      // Saves new journey and pops if successful.
      final success = await _journeyService.add(_journey!);

      if (success) {
        // DO NOT use BuildContext across asynchronous gaps.
        // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
        if (mounted) {
          NavigatorHelper.pop(context, EditJourneyResult(true));
        }
      }
    } else {
      // Updates journey and pops if successful.
      final success = await _journeyService.update(_journey!);

      if (success) {
        // DO NOT use BuildContext across asynchronous gaps.
        // https://dart-lang.github.io/linter/lints/use_build_context_synchronously.html
        if (mounted) {
          // Pops current page and returns to the detail view.
          // Pop method will not trigger WillPopScope.
          NavigatorHelper.pop(
            context,
            EditJourneyResult(true, journey: _journey),
          );
        }
      }
    }
  }

  /// Checks the data before popping.
  void _onPopInvokedWithResult(bool didPop, dynamic result) {
    if (didPop) {
      return;
    }

    // If we check the if the data identical that means we have to call [_formKey.currentState.save()] first.
    // Then it would call validation and might failed. That's why we show the confirm directly.
    showConfirmDialog(
      context,
      '放弃保存？',
      onConfirm: () {
        // If user pops current view directly, that means nothing updated.
        NavigatorHelper.pop(context, EditJourneyResult(false));
      },
    );
  }
}
